colorscheme:
yellow
violet
bw
Prihlásenie:
Login: Heslo:

Problem statement: zenit14skg

G: Animasembler
40 bodov Časový limit: 100 ms

Na to, aby zvieratká oklamali monitorovací systém záhrady, potrebujú preniknúť do tajov jeho softwarového a hardwarového vybavenia. Z dobre informovaných zdrojov sa dozvedeli, že programy ovládajúce kamery a alarm sú napísané v jazyku menom Animasembler. Tento jazyk je popísaný v texte nižšie. Pozor! Nenechajte sa odradiť dĺžkou tohto textu. Skrýva sa tam viac informácií, ako potrebujete pre účely tejto úlohy (ale neskôr na ZENITe sa zídu).

Aby zvieratká mohli niečo hacknúť, musia sa s jazykom zoznámiť. Napíšte im program, ktorý bude pre ich programy písané v jazyku Animasembler hovoriť, či sú tieto programy korektné. Pod slovom korektný rozumieme fakt, že sú to platné programy v tomto jazyku a nie, či robia niečo užitočné.

Popis jazyka Animasembler

Na každom riadku je direktíva, inštrukcia alebo komentár. Žiaden riadok nesmie byť prázdny. Program pracuje len s celými číslami v rozsahu 0 až 65,535 (nemá žiadne znaky, stringy, polia ani iné typy). Program môže načítavať čísla zo vstupu a vypisovať ich na výstup. Jazyk je citlivý na nadbytočný whitespace. Okrem medzier explicitne spomenutých v tejto špecifikácii sa v programe nesmú vyskytovať žiadne iné medzery. Program je case-sensitive: MenoPremennej a menoPremennej sú dve rôzne premenné.

Direktíva je riadok začínajúci bodkou. Každý program začína povinnou direktívou .program, za ktorou nasleduje jedna medzera a neprázdny reťazec – meno programu. Tento reťazec pozostáva z malých a veľkých písmen anglickej abecedy a jeho dĺžka nepresahuje 50.

Za prvým riadkom môže nasledovať 0 až neobmedzene veľa direktív .data, ktoré definujú premenné. Každý riadok s direktívou .data definuje jednu. Za direktívou .data nasleduje jedna medzera a meno premennej: neprázdny reťazec malých a veľkých písmen anglickej abecedy, ktorého dĺžka nepresahuje 50. Na začiatku behu programu má každá premenná hodnotu 0. Jedna premenná môže byť definovaná aj na viacerých riadkoch. Premenná môže mať rovnaký názov ako program. Nie je chybou, ak definujeme premennú a v programe ju nepoužijeme.

Za týmito riadkami nasleduje povinná direktíva .kod, ktorá označuje počiatočné miesto vykonávania programu. Táto direktíva nemá žiadne parametre, takže hneď sa znakom d nasleduje znak nového riadku. Jazyk nemá žiadne iné direktívy.

Za direktívou .kod nasleduje 0 až neobmedzene veľa inštrukcií – na každom riadku jedna. Inštrukcie jazyka sú popísané v nasledujúcej tabuľke spolu s definíciou ich prípadných parametrov. Keď sa spomína premenná, myslí sa tým premenná definovaná na začiatku programu direktívou .data. Žiadne iné premenné v jazyku nie sú. Všetky číselné rozsahy obsahujú aj obe okrajové hodnoty.

Formát inštrukcieParameter 1Parameter 2
scitaj par1 par2Celé číslo od 0 po 65,535 alebo premennáPremenná
odcitaj par1 par2 Celé číslo od 0 po 65,535 alebo premenná Premenná
vynasob par1 par2 Celé číslo od 0 po 65,535 alebo premenná Premenná
vydel par2 par2 Celé číslo od 0 po 65,535 alebo premenná Premenná
prirad par1 par2 Celé číslo od 0 po 65,535 alebo premenná Premenná
skocaknula par1 par2 Celé číslo od 0 po 65,535 alebo premenná Celé číslo od -65,535 po 65,535
skocaknenula par1 par2 Celé číslo od 0 po 65,535 alebo premenná Celé číslo od -65,535 po 65,535
nacitaj par1 Premenná -
vypis par1 Celé číslo od 0 po 65,535 alebo premenná -
skonci - -

Každý riadok s inštrukciou začína menom inštrukcie. Ak inštrukcia nemá parameter (napríklad skonci), potom hneď za jej menom nasleduje znak nového riadku. V prípade, že má inštrukcia parameter alebo parametre, sú tieto navzájom od názvu inštrukcie a od seba navzájom oddelené práve jednou medzerou. Každá inštrukcia sa môže vyskytnúť len s počtom parametrov podľa špecifikácie vyššie a tieto parametre musia spĺňať obmedzenia definované v tejto špecifikácii.

Pri vykonávaní aritmetických inštrukcií sa najprv načítajú hodnoty z premenných, potom sa vyhodnotí výsledok a až potom sa výsledok zapisuje. Je teda úplne v poriadku zavolať:

scitaj a a

Táto inštrukcia si interne vypočíta 2*a a potom túto hodnotu zapíše do premennej a. Jazyk pripúšťa len skutočné celočíselné konštanty a premenné. Nesmie sa použiť výraz. Nemôžeme teda napísať prirad 3+5 a ani scitaj a*3 b.

Hociktorý riadok v programe okrem prvého môže byt komentár. Takýto riadok začína znakom #, po ktorom môže nasledovať ľubovoľný reťazec písmen, medzier, čísiel, bodiek, znaku mínus a mriežok, ktorého dĺžka nepresahuje 100. Okrem obmedzenia dĺžky na tento reťazec nie sú kladené žiadne požiadavky.

Prvou inštrukciou, ktorá sa vykoná, je inštrukcia nasledujúca za direktívou .kod. Potom sa vykonávajú inštrukcie jedna za druhou s výnimkou inštrukcií skoku. Pri počítaní cieľového riadku skoku sa neberú do úvahy riadky s komentárom. Skok mimo program alebo na riadok s direktívou znamená ukončenie programu. Program končí aj vtedy, ak by sa mala vykonať inštrukcia nasledujúca za poslednou.

Pozor! Nové riadky v našich vstupných súboroch sú linuxové. To znamená, že nový riadok je tvorený jedným znakom s kódom 10 (line feed). Vo Windowse je nový riadok tvorený dvojicou znakov s kódmi 13 a 10 (carriage return + line feed). Dávajte si pozor, ak si u seba na windowsovom stroji testujete program.

Príklad programu v Animasembleri

Uveďme si ako príklad program Mocnina:

.program Mocnina
.data n
.data vysledok
.kod
nacitaj n
prirad 1 vysledok
# v n mame zapamatane kolkokrat este musime vynasobit vysledok hodnotou 2.
skocaknula n 4
vynasob 2 vysledok
odcitaj 1 n
# skocaknula 0 je priklad nepodmieneneho skoku.
skocaknula 0 -3
vypis vysledok
skonci

Tento program definuje dve premenné. Jednu hodnotu načíta zo vstupu, do druhej sa na úvod priradí 1. Potom sa opakuje cyklus, pri ktorom sa vynásobí premenná vysledok dvomi a odčíta od n jedna. Keď je hodnota n nula, program vypíše výsledok a skončí. Ak si hodnotu v premennej n interpretujeme ako počet, koľkokrát sa má ešte zopakovať cyklus, potom pomerne ľahko vidno, že náš program počíta n-tú mocninu čísla 2.

Poznamenajme, že v prípade, že sa na vstupe nachádza napríklad číslo n = 25, potom náš program skončí skôr, ako príde k výpisu: hodnota v premennej vysledok by totiž v istom momente behu bola príliš veľká.

Formát vstupu a výstupu

Na vstup je aspoň 1 a najviac 1000 riadkov. Na každom riadku je najviac 100 znakový reťazec pozostávajúci z medzier, čísel, bodiek, mriežok, znaku mínus, malých a veľkých písmen anglickej abecedy. Na každom riadku bude aspoň jeden znak, ktorý nie je medzera. Môžete predpokladať, že aj posledný riadok vstupu končí znakom nového riadku. Okrem toho o vstupe ale nič nepredpokladajte: môže to byť ľubovoľný guláš.

Na výstup vypíšte ANO alebo NIE podľa toho, či je text na vstupe validný program v jazyku Animasembler podľa špecifikácie vyššie.

Príklady

Input:

.program MojNajmilsi
.data oblubenaPremenna
.kod
skocaknenula 17 -23671
skonci

Output:

ANO

Tento program síce nič poriadne nerobí, ale zo syntaktického hľadiska je úplne správny. Hodnota ukazujúca mimo rozsah programu pri príkaze skoku nie je proti pravidlám.

Input:

#  komentar   namiesto  .mena programu.
.data dolezitaHodnota
.data esteDolezitejsiaHodnota
prirad esteDolezitejsiaHodnota Chobotina

Output:

NIE

Prvý riadok nesmie byť komentár. Chýbajú nám povinné direktívy .kod a .program a v priraďovacom príkaze používame meno nedefinovanej premennej.

Input:

.program snazil som sa
#nemozete od ludi chciet, aby
# vam programovali cely parser.
.data a
.kod
zarad 17
odcitaj  a  15
scitaj a 47 precoByScitajNemaloTriParametre
.uzmatonebavi

.kod

Output:

NIE

V mene programu nesmie byť medzera. Inštrukcia zarad nie je inštrukciou jazyka Animasembler. V riadku s inštrukciou odcitaj sa vyskytujú medzery navyše. Okrem toho nie je dodržaná požiadavka, že druhý parameter musí byť premenná. Inštrukcia scitaj má mať práve dva parametre (žiadna inštrukcia jazyka nemá tri parametre). Direktíva .uzmatonebavi nepatrí do jazyka a direktíva .kod sa v programe musí vyskytnúť práve raz a to medzi definíciou premenných a prvou inštrukciou. Prázdny riadok sa v korektnom programe nesmie vyskytnúť nikdy.


(C) MišoF, Zemčo. 2007 - 2013